perm filename SEEJOB.SAI[HAK,ROB] blob
sn#464919 filedate 1979-08-01 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00008 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 BEGIN "SEEJOB"
C00005 00003 ! program specific defines, etc
C00010 00004 ! Job info fetching routines
C00014 00005 ! Hash table routines
C00016 00006 ! User interface routines
C00017 00007 ! Display_the_Output routines
C00019 00008 ! The main program starts here
C00021 ENDMK
C⊗;
BEGIN "SEEJOB"
COMMENT Peek into another job's tables and display them. Maybe eventaully extend
to tell how much time is spent in certain loops, etc.;
REQUIRE "DDHDR.SAI[GRA,HPM]" SOURCE_FILE;
REQUIRE "LOITER.REL[HAK,ROB]" LOAD_MODULE;
REQUIRE "{}<>" DELIMITERS;
DEFINE !={COMMENT};
LET ⊂ = BEGIN, ⊃ = END, S⊂ = START_CODE, Q⊂ = QUICK_CODE;
DEFINE
SP={" "}, CR={('15&"")}, LF={('12&"")}, ↓={(CR&LF)}, TAB={('11&"")},
FF={('14&"")}, ALT={('175&"")},comma={", "};
DEFINE
THRU={STEP 1 UNTIL};
DEFINE
D$PRINT(str) = {IFC D$BUG THENC PRINT(str) ENDC},
D$ONLY(s) = {IFC D$BUG THENC ⊂ s ⊃ ENDC},
D$BUG ← {-1};
DEFINE PI = { 3.1415926536 };
DEFINE pos_int_infinity = { '377777777777 }; ! = 34359738367;
DEFINE neg_int_infinity = { '400000000000 }; ! = -34359738368;
DEFINE pos_real_infinity = { 1.70141182@38 }; ! just weird numbers that work;
DEFINE neg_real_infinity = { -1.69808878@38 };
DEFINE clear_screen = { CALL ((-1 LSH 18) + LOCATION ('004000000516), "TTYSET") };
DEFINE Quit = { BEGIN CALL(1,"EXIT"); END };
DEFINE ErrQuit(s) = { BEGIN PRINT(S); CALL(1,"EXIT"); END };
DEFINE LeftMask=(-1 LSH 18); ! Left half-word mask;
DEFINE RightMask=(-1 LSH -18); ! Right half-word mask;
DEFINE LeftHalf(Word)={((Word) LSH -18)}; ! Left half-word;
DEFINE RightHalf(Word)={((Word) LAND RightMask)}; ! Right half-word;
DEFINE XWD(Left,Right)={( ((Left) LSH 18) LOR ((Right) LAND RightMask) )};
! program specific defines, etc;
DEFINE
HashLen = 4663, HashMul = 761;
DEFINE MakSym(SYM,Val,Incr) =
{DEFINE SYM = {Val};
REDEFINE $Loc = {$Loc + Incr}};
DEFINE $Loc = 0;
DEFINE JDLen = '140; ! Length of JOB DATA AREA;
MakSym(JOBAC, '000,'20); ! PLACE WHERE USER ACS ARE STORED ON UUO CALLS;
MakSym(JOBDAC,'020,'20); ! PLACE WHERE HARDWARE ACS(0-16) ARE STORED;
MakSym(JOBUUO,'040,'01); ! USER UUO TRAP LOC.(UUO STORED HERE);
MakSym(JOB41, '041,'01); ! USER UUO JSR LOCATION;
MakSym(JOBERR,'042,'01); ! IN WHICH RPG SYSTEM PASSES ERRORS TO THE LOADER;
MakSym(JOBENB,'043,'01); ! LH=PC CHNG,AR OVF ENABLE/DISABLE APR BITS;
MakSym(JOBREL,'044,'01); ! LH=0,RH=HIGHEST REL. ADR. IN USER AREA;
MakSym(JOBTM1,'045,'05); ! SOME TEMP CELLS TOO;
MakSym(JOBPDL,'052,'16); ! PUSHDOWN LIST FOR GETPDL AND GIVPDL TO USE;
MakSym(JOBINT,'071,'01); ! TO SEPARATE OLD AND NEW INTERRUPT SYSTEMS;
MakSym(JOBHCU,'072,'01); ! HIGHEST USER IO CHANNEL IN USE;
MakSym(JOBPC, '073,'01); ! JOB PC WHEN JOB INACTIVE;
MakSym(JOBSAV,'073,'01); ! FIRST LOC.-1 WRITTEN BY SAVE COMMAND;
MakSym(JOBDDT,'074,'01); ! LH UNUSED,RH=STARTING ADDRESS OF USER DDT;
MakSym(JOBJDA,'075,'20); ! JOB DEVICE ASSIGNMENT TABLE;
MakSym(JOBPFI,'114,'01); ! HIGHEST LOC. IN JOB DATA AREA PROTECTED FROM IO;
MakSym(JOBHRL,'115,'01); ! HIGHEST ADDRESS OF UPPER SEGMENT;
MakSym(JOBSYM,'116,'01); ! POINTER TO LOADER AND DDT SYMBOL TABLE POINTER;
MakSym(JOBUSY,'117,'01); ! POINTER TO UNDEFINED SYMBOL TABLE;
MakSym(JOBSA, '120,'01); ! LH=FIRST LOC NOT LOADED BY RELOCATING LOADER;
MakSym(JOBFF, '121,'01); ! FIRST FREE LOCATION IN USER AREA;
MakSym(JOBS41,'122,'01); ! C(JOB41) SAVED HERE ON SAVE COMMAND;
MakSym(JOBEXM,'123,'01); ! LAST LOC EXAMINED OR DEPOSITED USING ;
MakSym(JOBREN,'124,'01); ! REENTER ADDRESS FOR REENTER COMMAND;
MakSym(JOBAPR,'125,'01); ! PLACE TO TRAP TO IN USER AREA ON APR TRAP;
MakSym(JOBCNI,'126,'01); ! APR IS CONIED INTO C(JOBCNI) ON APR TRAP;
MakSym(JOBTPC,'127,'01); ! PC IS STORED HERE ON USER APR TRAP;
MakSym(JOBOPC,'130,'01); ! OLD PC IS STORED HERE ON START,DDT,REENTER,;
MakSym(JOBCHN,'131,'01); ! LH=FIRST LOC AFTER FIRST FORTRAN 4 LOADED PROGRAM;
MakSym(JOBFDV,'132,'01); ! DEV. DATA BLOCK ADR. FOR FINISH COMMAND;
MakSym(JOBCOR,'133,'01); ! SIZE OF CORE FOR JOB ON RUN,SAVE,GET COM.;
MakSym(HINAME,'134,'01); ! NAME OF UPPER SEGMENT OVER SAVE-GET;
MakSym(HILOC, '135,'01); ! LOC OF UPPER SEGMENT IN DUMP FILE OVER SAVE-GET;
MakSym(JOBVER,'137,'01); ! JOB VERSION;
MakSym(JOBDA ,'140,'00); ! FIRST LOC NOT USED BY JOB DATA AREA;
! Job info fetching routines;
INTEGER PROCEDURE GetJDA(INTEGER JobNo; INTEGER ARRAY InfBlk);
! The JOBRD UUO does a Block Transfer (BLT) of some job's (partial) core
image
into your own. This routine uses this UUO to fetch the Job Data
Area" (locations '0-JDLen) of JobNo into the specified array (InfBlk).
The routine will return False (=0) if there was no error, and a (small)
negative integer (see UUO manual page 149) to indicate an error;
S⊂
LABEL JobBlk,GetJD1;
DEFINE JOBRD = {'400050}, NWC = {-JDLen};
MOVEI 3,JobBlk ;
MOVE 2,JobNo ;
MOVEM 2,0(3) ;
MOVSI 2,NWC ;
MOVEM 2,1(3) ; ! -word count,,0
MOVE 2,InfBlk ;
MOVEM 2,2(3) ;
SETZM 1 ; ! error ← FALSE;
CALLI 3,JOBRD ;
MOVN 1,1(3) ; ! if error, then return -cause in register 1;
JRST GetJD1 ;
JobBlk: 0 ; ! Job number for JOBRD;
0 ; ! -Word Count,,Starting Address;
0 ; ! address of where data gets stored;
GetJD1:
⊃;
INTEGER PROCEDURE GetJPC(INTEGER JobNo);
! The routine will return 0 if there was no error, and a (small)
negative integer (see UUO manual page 149) to indicate an error;
S⊂
LABEL JobBlk,GetJP1;
DEFINE JOBRD = {'400050};
MOVEI 3,JobBlk ;
MOVE 2,JobNo ; ! Set the Job Number for JOBRD;
MOVEM 2,0(3) ;
HRROI 2,JobPC ; ! WCMA = -1,,JobPC (fetch 1 word starting at JobPC);
MOVEM 2,1(3) ;
MOVEI 2,1 ; ! Set the destination for JOBRD ( = register 1);
MOVEM 2,2(3) ;
! SETZM 1 ; ! error ← FALSE (commented out because 1 is always set);
CALLI 3,JOBRD ;
MOVN 1,1(3) ; ! if error, then return cause in register 1;
JRST GetJP1 ;
JobBlk: 0 ; ! Job number for JOBRD;
0 ; ! -Word Count,,Starting Address;
0 ; ! address of where data gets stored;
GetJP1:
⊃;
INTEGER PROCEDURE GetTTI(INTEGER JobNo);
! This routine will return the total run time (in tics) of
the specified job. The SETMAP routine *must* be called
once before this routine can be executed;
DEFINE TTIME = {'400214};
S⊂
MOVE 2,TTIME ; ! Fetch the address of the TTIME job table;
ADD 2,JobNo ; ! Index using Job Number;
MOVE 1,'400000(2) ; ! Fetch the TTIME;
⊃;
PROCEDURE SetMap;
! This routine maps the system table as an upper segment to this
job. It must be called before attempting to read the system
tables;
DEFINE SETPR2 = {'400052};
S⊂
MOVSI 1,'377777 ;
CALLI 1,SETPR2 ;
JRST 4, ; ! error return - help! ;
⊃;
! Hash table routines;
! these routines use the (globally defined) symbols Hashlen and HashMul.
The algorithm used is MHASH(val) = (val * HashMul) MOD HashLen;
INTEGER PROCEDURE Mhash(INTEGER val);
! This routine returns a hashed value between 0 and HashLen-1;
Q⊂
MOVE 1,val ;
IMULI 1,HashMul ; ! Some number relatively prime to HashLen;
IDIVI 1,HashLen ;
MOVE 1,2 ; ! Return val MOD HashLen;
⊃;
INTEGER PROCEDURE EnHash(INTEGER val; INTEGER ARRAY HashTab);
! Returns index into HashTab, inserting HASH(val) as needed;
! This routine would do well to be START_CODED (ROB 31-Jul-79);
⊂
DEFINE the_cows_come_home = {FALSE};
INTEGER indx, first;
indx ← first ← Mhash(val);
DO
⊂
IF HashTab[indx] = val THEN RETURN(indx);
IF HashTab[indx] = 0 THEN ⊂ HashTab[indx] ← val; RETURN(indx) ⊃;
IF (indx ← indx + 1 MOD HashLen) = first THEN ErrQuit("Hash table full!");
⊃
UNTIL the_cows_come_home;
⊃;
! User interface routines;
PROCEDURE SetLimits(
INTEGER char;
REFERENCE INTEGER Lo_X, Lo_Y, Hi_X, Hi_Y);
! This routine will set the X and Y scale according to what
characters have been typed;
⊂ "SetLimits"
! CASE MakeUpper(char) OF BEGIN
["("]
[")"]
["["]
["]"]
["/"]
["\"]
["∂"]
["∞"]
["B"]
["T"]
END;
⊃ "SetLimits";
! Display_the_Output routines;
PROCEDURE DumpArray(INTEGER ARRAY PCs, Hits; INTEGER count);
! Used as a quick and dirty way to see the results;
⊂ "DumpArray"
INTEGER I;
PRINT(↓,"Loc",tab,"hits",tab,"percent of total",↓);
FOR I ← 0 THRU HashLen - 1 DO
IF Hits[I] ≠ 0 THEN
PRINT(CVOS(PCs[I]),tab,Hits[I],tab,(Hits[I]*100)/count,"%",↓);
⊃ "DumpArray";
PROCEDURE DPYArray(
INTEGER ARRAY PCs, Hits;
INTEGER count, xlo, ylo, xhi, yhi, DDChan);
⊂ "DPYArray" INTEGER I;
LITEN;
SCREEN(xlo, ylo, xhi, yhi);
ERASE(DDChan);
LINE(xlo,ylo,xlo,yhi);
FOR I ← 0 THRU HashLen - 1 DO
IF Hits[I] ≠ 0 THEN LINE(xlo, PCs[I], Hits[I]/count, PCs[I]);
DPYUP(DDChan);
⊃; "DPYArray";
! The main program starts here;
DEFINE xlo = 0, xhi = 100, ylo = 0, yhi = 100;
DEFINE cvhwos(v) = {CVOS(RightHalf(v))};
INTEGER ARRAY HashTab[0:HashLen-1];
INTEGER ARRAY HitFreq[0:HashLen-1];
INTEGER JobNum, err, count, I, pc_of_interest, NSamps, LastTic, CurrTic, DDChan;
INTEGER xl,yl,xh,yh;
xl ← 0; yl ← 0; xh ← .2; yh ← 40000;
SetMap;
PRINT("Job Number :");JobNum ← CVD(INCHWL);
arrclr(HashTab);
arrclr(HitFreq);
LastTic ← 0;
count ← 0;
DDChan ← GDDCHN(-1); ! Fetch us a channel;
DDINIT; ! initialize the DD buffer;
SHOW(DDChan);
WHILE TRUE DO IF (pc_of_interest ← GetJPC(JobNum)) < 0
THEN
PRINT("error code = ",err,↓)
ELSE ⊂
count ← count + 1;
pc_of_interest ← RightHalf(pc_of_interest);
I ← EnHash(pc_of_interest, HashTab);
HitFreq[I] ← HitFreq[I] + 1;
WHILE (CurrTic ← GetTTI(JobNum)) = LastTic DO CALL(0,"SLEEP");
LastTic ← CurrTic;
IF NOT(count MOD 10) THEN DPYArray(HashTab,HitFreq,count,xl,yl,xh,yh,DDChan);
⊃;
END "SEEJOB";